package service;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.jws.WebMethod;
import javax.jws.WebService;

import server.LhSwingServer;
import br.org.lh.ClientSwing.extendedElements.utils.UIBindingUtil;

/**
 * Web service that acts as a proxy to all the server-based RN classes.
 * 
 * @author Luiz H.Rolim
 * @version 1.0
 * 
 */
@WebService(endpointInterface = "service.IServiceGenericInvoker", serviceName = "lhInvoker")
public class GenericWebServiceInvoker implements IServiceGenericInvoker {

	private GenericWebServiceInvoker() {
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see service.IServiceGenericInvoker#invoke(java.lang.String,
	 *      java.lang.String, java.lang.Object[])
	 */
	@Override
	@WebMethod
	public WebServicePojo invoke(String controllerClassPath,
			String methodName, Object[] parameterList) {
		try {
			Object controllerObject = LhSwingServer.getControllerObject(controllerClassPath);
			Method method = controllerObject.getClass().getMethod(methodName,
					getParameterTypes(parameterList));
			Object methodReturn = method
					.invoke(controllerObject, parameterList);
			Map<String, Object> paramMap = getParamMap(controllerObject);
			WebServicePojo returnType = new WebServicePojo(
					methodReturn, paramMap);
			return returnType;

		
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;

	}

	private Map<String, Object> getParamMap(Object controllerObject) {
		List<Method> getters = UIBindingUtil.getGettersList(controllerObject);
		Map<String, Object> returnMap = new LinkedHashMap<String, Object>(
				getters.size());
		for (Method getter : getters) {
			String fieldId = UIBindingUtil.getFieldNameByGetter(getter
					.getName());
			Object value = UIBindingUtil.invokeGetter(getter, controllerObject);
			if (AcochambratedEncoderDecoder.checkIfFieldIsArray(value))
				AcochambratedEncoderDecoder.encode(fieldId, value, returnMap);
			else
				returnMap.put(fieldId, value);
		}

		return returnMap;
	}

	
	

	private Class<?>[] getParameterTypes(Object[] parameterList) {
		if (parameterList == null || parameterList.length == 0)
			return null;
		List<Class<?>> classList = new ArrayList<Class<?>>();
		for (Object parameter : parameterList)
			classList.add(parameter.getClass());
		return (Class[]) classList.toArray();
	}

	public static GenericWebServiceInvoker getInstance() {
		return Singleton.getInstance();
	}

	private static class Singleton {

		private static final GenericWebServiceInvoker SINGLETONHOLDER = new GenericWebServiceInvoker();

		private static final GenericWebServiceInvoker getInstance() {
			return SINGLETONHOLDER;
		}

	}

	@Override
	@WebMethod
	public void updateModel(String controllerClassPath,
			WebServicePojo webServicePojo) {
		Object controller = LhSwingServer.getControllerObject(controllerClassPath);
		webServicePojo.setModelValues(AcochambratedEncoderDecoder.decodeMap(webServicePojo.getModelValues()));
		for (String s : webServicePojo.getModelValues().keySet())
			UIBindingUtil.setFieldValue(s, controller, webServicePojo.getModelValues().get(s));
		
	}

	@Override
	public WebServicePojo getModelData(String controllerPath) {
		Object controllerObject = LhSwingServer.getControllerObject(controllerPath);
		return new WebServicePojo (null, getParamMap(controllerObject));
	}
	
	
	

}
